package com.xiaokaceng.openci.application.impl;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.inject.Inject;
import javax.inject.Named;

import org.apache.commons.lang3.StringUtils;
import org.dayatang.querychannel.Page;
import org.dayatang.querychannel.QueryChannelService;
import org.openkoala.auth.application.UserApplication;
import org.openkoala.auth.application.vo.RoleVO;
import org.openkoala.auth.application.vo.UserVO;
import org.openkoala.koala.auth.core.domain.Role;
import org.openkoala.koala.auth.core.domain.User;
import org.openkoala.koala.auth.password.PasswordEncoder;
import org.openkoala.koala.auth.ss3adapter.ehcache.CacheUtil;
import org.springframework.transaction.annotation.Transactional;

import com.xiaokaceng.openci.application.DeveloperApplication;
import com.xiaokaceng.openci.domain.Developer;
import com.xiaokaceng.openci.dto.DeveloperDto;

@Named("developerApplication")
@Transactional("transactionManager_opencis")
public class DeveloperApplicationImpl implements DeveloperApplication {

	@Inject
	private QueryChannelService queryChannel;

	@Inject
	private UserApplication userApplication;
	
	@Inject
	private PasswordEncoder passwordEncoder;
	
	private static final String DEVELOPER_ROLE = "developer";
	
	@SuppressWarnings("unchecked")
	public Page<DeveloperDto> pagingQeuryDevelopers(Developer example, int currentPage, int pagesize) {
		StringBuilder jpql = new StringBuilder();
		jpql.append("SELECT new com.xiaokaceng.openci.dto.DeveloperDto(_developer.id, _developer.developerId, _developer.name,  _developer.email, _developer.password) ");
		jpql.append("FROM Developer _developer WHERE _developer.createDate <= :queryDate AND _developer.abolishDate > :queryDate ");

		Date now = new Date();
		Map<String, Object> conditionVals = new HashMap<String, Object>();
		conditionVals.put("queryDate", now);

		if (!StringUtils.isBlank(example.getName())) {
			jpql.append(" and _developer.name like :name");
			conditionVals.put("name", "%" + example.getName() + "%");
		}
		if (!StringUtils.isBlank(example.getDeveloperId())) {
			jpql.append(" and _developer.developerId like :developerId");
			conditionVals.put("developerId", "%" + example.getDeveloperId() + "%");
		}
		if (!StringUtils.isBlank(example.getEmail())) {
			jpql.append(" and _developer.email like :email");
			conditionVals.put("email", "%" + example.getEmail() + "%");
		}

		return queryChannel.createJpqlQuery(jpql.toString()).setParameters(conditionVals).setPage(currentPage, pagesize).pagedList();
	}

	public void createDeveloper(Developer developer) {
		Role role = Role.findRoleByName(DEVELOPER_ROLE);
		if(role == null){
			//如果角色不存在,抛出异常
			throw new RuntimeException("Role["+DEVELOPER_ROLE+"] not exists!");
		}
		// 保存用户
		UserVO user = new UserVO();
		user.setEmail(StringUtils.trim(developer.getEmail()));
		user.setName(StringUtils.trim(developer.getName()));
		user.setUserAccount(StringUtils.trim(developer.getDeveloperId()));
		user.setSerialNumber("0");
		user.setUserPassword(passwordEncoder.encode(developer.getPassword()));
		user.setValid(true);
		user = userApplication.saveUser(user);
		CacheUtil.refreshUserAttributes(user.getUserAccount());
		
		RoleVO roleVo = new RoleVO();
		roleVo.setId(role.getId());
		userApplication.assignRole(user, roleVo);
		CacheUtil.refreshUserAttributes(((UserVO) userApplication.getUser(user.getId())).getUserAccount());
		//

		developer.setDeveloperId(StringUtils.trim(developer.getDeveloperId()));
		developer.save();
	}

	public void updateDeveloper(Developer developer) {
		Developer developer2 = Developer.get(Developer.class, developer.getId());
		developer2.setName(developer.getName());
		developer2.setEmail(developer.getEmail());
		developer2.save();
	}

	public void abolishDeveloper(Developer developer) {
		User user = User.findByUserAccount(developer.getDeveloperId());
		if (user != null) {
			this.userApplication.removeUser(Long.valueOf(user.getId()));
			CacheUtil.removeUserFromCache(user.getUserAccount());
		}
		Developer needRemoveDeveloper = Developer.get(Developer.class, developer.getId());
		needRemoveDeveloper.abolish(new Date());
	}

	public void abolishDevelopers(Collection<Developer> developers) {
		for (Developer developer : developers) {
			abolishDeveloper(developer);
		}
	}

	public boolean checkDeveloperIdIsExist(String developerId) {
		return Developer.checkDeveloperIdIsExist(developerId);
	}

	public List<DeveloperDto> findByDeveloperId(String developerId) {
		return DeveloperDto.transformBy(Developer.findByDeveloperId(developerId));
	}

	@Override
	public Developer getByDeveloperId(String developerId) {
		return Developer.getByDeveloperId(developerId);
	}
}
